package com.asiainfo.ai.admin.utils;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

import org.springframework.util.Base64Utils;
import org.springframework.util.DigestUtils;

import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import java.util.Base64;

/**
 * 符合业界安全标准的密码hash处理,涉及的加密算法不要改动！！！
 * **/
@Slf4j
public class PasswordHashUtil {
	public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA256";
	public static final int SALT_SIZE = 32;
	public static final int HASH_SIZE = 256;
	public static final int PBKDF2_ITERATIONS = 10000;

	public static void main(String[] args) throws Exception {
		 
	}

	public static String decriptAES(String SecretText, String key, String iv) throws Exception {
		try {

			byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
			byte[] ivBytes = iv.getBytes(StandardCharsets.UTF_8);

			SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
			IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);

			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

			cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);

			byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(SecretText));
			String decryptedResult = new String(decryptedBytes, StandardCharsets.UTF_8);
			
			return decryptedResult;
		}
		catch (Exception e) {
			String msg = "AES解密失败 - " + e.getMessage();
			log.error(msg, e);
			throw new RuntimeException(msg);
		}

	}
	
    public static String decryptByWeb(String userId, String passwdBase64) {
        byte[] data = Base64Utils.decodeFromString(passwdBase64);
        //这里需要md5是为了保证密钥长度
        byte[] key = DigestUtils.md5Digest(userId.getBytes(StandardCharsets.UTF_8));
        try {
            SecretKey k = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            // 初始化，设置为加密模式
            cipher.init(Cipher.DECRYPT_MODE, k);
            // 执行操作
            return new String(cipher.doFinal(data), StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("fail to decrypt", e);
        }
    }

	public static String hash(String password, String salt) {
		try {
			return getPBKDF2(password, salt);
		}
		catch (Exception e) {
			throw new RuntimeException("fail to hash", e);
		}
	}

	public static String getRandomSalt() {
		try {
			SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
			byte[] bytes = new byte[SALT_SIZE / 2];
			random.nextBytes(bytes);
			return DatatypeConverter.printHexBinary(bytes);
		}
		catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 前端form提交的加密方式
	 * @Description 
	 * @param key
	 * @param str
	 * @return
	 * @throws Exception
	 */
	public static String encryptByWeb(String userId, String pwd) throws Exception {
		// 计算MD5摘要
		MessageDigest md = MessageDigest.getInstance("MD5");
		byte[] keyBytes = md.digest(userId.getBytes(StandardCharsets.UTF_8));
		SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");

		// 创建AES加密器
		Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
		cipher.init(Cipher.ENCRYPT_MODE, secretKey);

		// 加密
		byte[] encryptedBytes = cipher.doFinal(pwd.getBytes(StandardCharsets.UTF_8));
		return Base64.getEncoder().encodeToString(encryptedBytes);
	}

	private static String getPBKDF2(String password, String salt) throws Exception {
		byte[] bytes = DatatypeConverter.parseHexBinary(salt);
		KeySpec spec = new PBEKeySpec(password.toCharArray(), bytes, PBKDF2_ITERATIONS, HASH_SIZE);
		SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM);
		byte[] hash = secretKeyFactory.generateSecret(spec).getEncoded();
		return DatatypeConverter.printHexBinary(hash);
	}
}
